package dymnd.net.server;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.LinkedList;

import dymnd.net.Packet;

public class Server implements Runnable{
	int port = 5000;
	LinkedList<ClientItem> clients = new LinkedList<ClientItem>();
	
	boolean nonAdminAddLayers = true;
	int layerCount = 0;
	
	public static void main(String[] args)	{
		new Server(5000).start();
	}
	
	
	public Server(int port)	{
		//ServerSocketThread serverSocketThread = new ServerSocketThread();
		this.port = port;
	}
	
	public void start()	{
		new Thread(this).start();
	}
	/**
	 * Called by the ServerSocketThread to add a new client that has successfully handshaken with the server
	 * 
	 * @param c - the client to be added
	 */
	private synchronized void addClient(ClientItem c)	{
		clients.add(c);
	}
	
	public void run()	{
		ServerSocketThread sockThread = new ServerSocketThread();
		sockThread.port = port;
		new Thread(sockThread).start();
		
		//main server loop here
		while(true)	{
			//process and check all clients for sent data
			for(int i = 0; i < clients.size(); i++)	{
				try {
					if(clients.get(i).available())	{
						Packet p = (Packet) clients.get(i).in.readObject();
						if(p.packetType == Packet.PACKET_TYPE_PLUGIN)	{
							broadcastPacket(p, false);
							System.out.println("Writing packet from user: " + clients.get(i).username);
						} else if(p.packetType == Packet.PACKET_TYPE_NATIVE)	{
							if(p.nativeCommand == Packet.NATIVE_ADD_LAYER)	{
								layerCount++;
								broadcastPacket(p, true);
							}
							
						}
					}
				} catch (IOException e) {
					e.printStackTrace();
				} catch (ClassNotFoundException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
		
		
	}
	
	private void broadcastPacket(Packet p, boolean originator)	{
		for(int i = 0; i < clients.size(); i++)	{
			if(!clients.get(i).username.equalsIgnoreCase(p.username) || originator)
				try {
					clients.get(i).out.writeObject(p);
				} catch (IOException e) {
					e.printStackTrace();
				}
		}
	}
	
	
	public void stop()	{
		
	}
	
	
	private class ServerSocketThread implements Runnable	{
		boolean stopping = false;
		int port = 5000;
		public void run()	{
			while(!stopping)	{
				try {
				
					ServerSocket servSock = new ServerSocket(port);
					Socket s = servSock.accept();
					servSock.close();
					
					ClientItem c = new ClientItem(s);
					Packet p = new Packet();
					c.handshake(p);
					addClient(c);
					
				} catch (IOException e) {
					e.printStackTrace();
				}
				
			}
		}
	}
}

class ClientItem	{
	private Socket socket = null;
	ObjectInputStream in;
	ObjectOutputStream out;
	String username = null;
	public ClientItem(Socket s)	{
		socket = s;
	}
	
	public boolean available() throws IOException	{
		if(socket.getInputStream().available() > 0)
			return true;
		else 
			return false;
	}
	
	public boolean handshake(Packet p)	{
		try {
			out = new ObjectOutputStream(socket.getOutputStream());
			//write an output packet to the client here, then...
			out.writeObject(p);
			
			in = new ObjectInputStream(socket.getInputStream());
			Packet pack = (Packet)in.readObject();
			this.username = pack.username;
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return true;
	}
	
}


